﻿using ShipsLog.Model;
using System;
using System.Collections.Generic;
using System.Speech.Recognition;
using System.Speech.Synthesis;
using System.Threading.Tasks;
using System.Windows.Forms;
using InputManager;

namespace Verball
{
    public class Verbliser : IDisposable
    {
        private KeysConverter KeyConverter = new KeysConverter();
        private SpeechRecognitionEngine recognizer;
        private SpeechSynthesizer synthia;

        private Dictionary<string, Action<RecognitionResult>> commands = new Dictionary<string, Action<RecognitionResult>>();
        private Task worker;
        private ShipsModelControl model;
        private string updateSsml = "<?xml version=\"1.0\"?><speak version=\"1.0\" xmlns=\"http://www.w3.org/2001/10/synthesis\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://www.w3.org/2001/10/synthesis http://www.w3.org/TR/speech-synthesis/synthesis.xsd\" xml:lang=\"en-GB\">Profile Updated</speak>";

        private void Init()
        {
            try
            {
                this.synthia = new SpeechSynthesizer();
                this.synthia.Volume = Convert.ToInt32(this.synthia.Volume * 0.8);
                this.synthia.SetOutputToDefaultAudioDevice();
                this.synthia.Rate = (int)(this.synthia.Rate * 0.4);

                recognizer = new SpeechRecognitionEngine();
                recognizer.LoadGrammarCompleted +=
                  new EventHandler<LoadGrammarCompletedEventArgs>(recognizer_LoadGrammarCompleted);
                recognizer.SpeechRecognized +=
                  new EventHandler<SpeechRecognizedEventArgs>(recognizer_SpeechRecognized);

                this.commands["menu"] = (s) =>
                {
                    switch (s.Text)
                    {
                        case "status":
                            this.model.MenueMode = 0;
                            break;
                        case "ship":
                            this.model.MenueMode = 1;
                            break;
                        case "commodities":
                            this.model.MenueMode = 2;
                            break;
                        case "recommendation":
                            this.model.MenueMode = 3;
                            break;
                        case "screen grabs":
                            this.model.MenueMode = 4;
                            break;
                        case "update":
                            this.model.Update(true);
                            break;
                        case "settings":
                            this.model.MenueMode = 5;
                            break;
                    }
                };

                this.commands["keyBinding"] = (s) =>
                {
                    try
                    {
                        string x = s.Semantics["KeyPress"].Value.ToString();
                        var key = (System.Windows.Forms.Keys)this.KeyConverter.ConvertFromString(x);
                        Keyboard.KeyPress(key, 100);
                    }
                    catch (Exception e)
                    {
                        var t = e;
                    }
                    //SendKeys.Send(x);
                };

                var menuGrammar = new Grammar("./Grammar.xml", "menu");
                menuGrammar.Name = "menu";
                recognizer.LoadGrammar(menuGrammar);
                var keysGrammar = new Grammar("./Grammar.xml", "keyBinding");
                keysGrammar.Name = "keyBinding";
                recognizer.LoadGrammar(keysGrammar);
                recognizer.SetInputToDefaultAudioDevice();
                recognizer.RecognizeAsync(RecognizeMode.Multiple);
            }
            catch (Exception e)
            {
                var x = e;
            }
        }

        public Verbliser(ShipsModelControl model)
        {

            this.model = model;
            this.Init();
        }

        private void recognizer_SpeechRecognized(object sender, SpeechRecognizedEventArgs e)
        {
            
            if (this.commands.ContainsKey(e.Result.Grammar.RuleName))
            {
                this.commands[e.Result.Grammar.RuleName](e.Result);
            }
        }

        // Handle the LoadGrammarCompleted event.
        private void recognizer_LoadGrammarCompleted(object sender, LoadGrammarCompletedEventArgs e)
        {
            string grammarName = e.Grammar.Name;
            bool grammarLoaded = e.Grammar.Loaded;

            if (e.Error != null)
            {
                //this.infoStream(string.Format("LoadGrammar for {0} failed with a {1}.",
                //grammarName, e.Error.GetType().Name));

                // Add exception handling code here.
            }

            //this.infoStream(string.Format("Grammar {0} {1} loaded.",
            //grammarName, (grammarLoaded) ? "is" : "is not"));
        }

        // Put the shared speech recognizer into "listening" mode.


        public void Dispose()
        {
            if (recognizer != null)
            {
                recognizer.Dispose();
            }
        }

        public void UpdateSucessfull()
        {
            this.synthia.SpeakSsml(this.updateSsml);
        }

        public void Say(string p)
        {
            this.synthia.Speak(p);
        }
    }
}